package preprocess;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException;


public class HeatMapCreator {
	
	
	static CityStatsReader csr;
	
	
	private double north;
	private double south;
	private double east;
	private double west;
	
	public void printMap(List<String> files, String out_dir, int h) {
		try {
			new File(out_dir).mkdir();
			
			File fh = new File(out_dir+"heat.kml");
			if(fh.exists()) {
				System.out.println("Skipping "+out_dir);
				return;
			}
			
			
			PrintWriter out = new PrintWriter(new FileWriter(new File(out_dir+"heat.kml")));
			out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
			out.println("<kml xmlns=\"http://earth.google.com/kml/2.2\">");
			out.println("<Folder>");
			out.println("<name>"+out_dir.substring(out_dir.indexOf("/")+1)+"</name>");
			
		
			for(String f: files) {
				if(f.endsWith(".csv")) {
					String n = f.substring(f.lastIndexOf("/")+1);
					String t = n.substring(n.length()-"00-00.csv".length(),n.indexOf(".csv"));
					
					int index = -1;
					if(t.equals("00_07")) index = 0;
					if(t.equals("08_13")) index = 1;
					if(t.equals("14_17")) index = 2;
					if(t.equals("18_24")) index = 3;	
					
					printMap(f,index,out_dir,out);
				}
			}
			
			out.println("</Folder>");
			out.println("</kml>");
			out.close();
			
			
			System.out.println("Starting Python at "+new File(out_dir).getAbsolutePath());
			Process p=Runtime.getRuntime().exec("heatmap-1.0/gheat.bat \""+new File(out_dir).getAbsolutePath()+"\" "+h); 
			BufferedReader br_err = new BufferedReader(new InputStreamReader(p.getErrorStream()));
			BufferedReader br_out = new BufferedReader(new InputStreamReader(p.getInputStream()));
			String line;
			while ((line = br_out.readLine()) != null) 
				System.out.println(line);
			
			while ((line = br_err.readLine()) != null) 
				System.err.println(line);
			
			p.waitFor(); 
			
			
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	
	
	String label[] = {"night","morning","afternoon","evening"};
	
	String[][] times = new String[][]{
			{"2010-11-07T01:00:00Z","2010-11-07T08:00:00Z"},
			{"2010-11-07T08:00:00Z","2010-11-07T14:00:00Z"},
			{"2010-11-07T14:00:00Z","2010-11-07T18:00:00Z"},
			{"2010-11-07T18:00:00Z","2010-11-07T23:59:59Z"},
	};
	
	
	private void printMap(String csv, int index, String dir, PrintWriter out) throws Exception {
		
		List<double[]> matrix = new ArrayList<double[]>();
		BufferedReader br = new BufferedReader(new FileReader(new File(csv)));
		String line;
		while((line = br.readLine()) != null) {
			String[] token = line.split(",");
			double lat = Double.parseDouble(token[0]);
			double lon = Double.parseDouble(token[1]);
			double val = Double.parseDouble(token[2]);
			matrix.add(new double[]{lat,lon,val});
		}
		
	
		File f = new File(dir+index+".txt");
		PrintWriter out_txt = new PrintWriter(new FileWriter(f));
		
		
		double min_x = Double.MAX_VALUE;
		double min_y = Double.MAX_VALUE;
		double max_x = -Double.MAX_VALUE;
		double max_y = -Double.MAX_VALUE;
		
		for(int k=0; k<matrix.size();k++) {
			double y = matrix.get(k)[0];
			double x = matrix.get(k)[1];
			
			if(x>-50) System.out.println(f);
			
			min_x = Math.min(min_x, x);
			min_y = Math.min(min_y, y);
			max_x = Math.max(max_x, x);
			max_y = Math.max(max_y, y);
		}
		
		
		
		double z = 0.05;
		max_x = max_x + z;  
		max_y = max_y + z;
		min_x = min_x - z; 
		min_y = min_y - z;
		
		
		
		north = max_y;
		south = min_y;
		west = min_x;
		east = max_x;
		
	
		
		out_txt.println(min_x+","+min_y);
		out_txt.println(max_x+","+max_y);
		
		int how_many_points = 0;
		for(int i=0; i<matrix.size();i++) {
			
			double lat = matrix.get(i)[0];
			double lon = matrix.get(i)[1];
			double val = matrix.get(i)[2];
			
			int n_points = (int)(val/15);
			
			if(n_points < 3) n_points = 0;
			
			double noise = 0.01;
			double x,y;
			for(int k=0; k<n_points;k++) {
				how_many_points ++;
				x = lon + noise*(0.5 - Math.random());
				y = lat + noise*(0.5 - Math.random());
				min_x = Math.min(min_x, x);
				min_y = Math.min(min_y, y);
				max_x = Math.max(max_x, x);
				max_y = Math.max(max_y, y);
				out_txt.println(x+","+y);
			}
		}
		out_txt.close();
		/*
		if(how_many_points < 2) {
			System.out.println("********** DELETING: "+f.getAbsolutePath());
			f.delete();
		}
		*/
		// compile the main kml accordingly
		out.println("<Folder>");
		out.println("<name>"+label[index]+"</name>");
		out.println("<TimeSpan>");
		out.println("<begin>"+times[index][0]+"</begin>");
		out.println("<end>"+times[index][1]+"</end>");
		out.println("</TimeSpan>");
		
		
		if(how_many_points >= 2) {
			out.println("<GroundOverlay>");
			out.println("<Icon>");
			out.println("<href>"+index+".png</href>");
			out.println("</Icon>");
			out.println("<LatLonBox>");
			out.println("<north>"+max_y+"</north>");
			out.println("<south>"+min_y+"</south>");
			out.println("<east>"+max_x+"</east>");
			out.println("<west>"+min_x+"</west>");
			out.println("<rotation>0</rotation>");
			out.println("</LatLonBox>");
			out.println("</GroundOverlay>");
		}
		out.println("</Folder>");
	}
	
	
	public void insert(String city, String state, String activity, int[] nuser, int[] ntrack, int population, double north, double south, double west, double east) {
		try {
			Class.forName("com.mysql.jdbc.Driver").newInstance();
		    Connection c = DriverManager.getConnection("jdbc:mysql://localhost:3306/nstweb?user=root&password=root");
		    Statement s = c.createStatement();	
			
		    
		    String bbox = "GeomFromText('MULTIPOINT("+west+" "+south+","+east+" "+south+","+east+" "+north+","+west+" "+north+")')";
		    
		    String insert = "INSERT INTO overlay VALUES('"+city+"','"+state+"','"+activity+"',"+bbox+","+
		    north+","+south+","+east+","+west+","+
		    nuser[0]+","+ntrack[0]+","+nuser[1]+","+ntrack[1]+","+nuser[2]+","+ntrack[2]+","+nuser[3]+","+ntrack[3]+","+
		    population+")";
			//System.out.println(insert);
			s.executeUpdate(insert);	
			
			s.close();
			c.close();

		} catch(Exception e) {
			if(!e.toString().contains("Duplicate entry"))
			 e.printStackTrace();
		}
	}
	
	
	public static void parseCity(String dir) {
		String name = dir.substring(dir.lastIndexOf("/")+1);
		String state = name.substring(0,name.indexOf("-"));
		String city = name.substring(name.indexOf("-")+1);
		
		//System.out.println(city+" ("+state+")");
		//System.out.println(dir);
		File fdir = new File(dir);
		File[] files = fdir.listFiles();
		
		
		String[] activities = new String[]{"cycling","running","walking"};
		
		for(String activity : activities) {
			
			List<String> fcsv = new ArrayList<String>();
			
			for(File f: files) {
				String fn = f.getName().toLowerCase();
				if(fn.endsWith(".csv") && fn.contains(activity))
					fcsv.add(f.getAbsolutePath());
			}
			
			createMaps(city, state, activity, fcsv);
		}
		
	}
	
	
	
	
	
	public static void createMaps(String city, String state, String activity, List<String> files) {
		String outdir = "D:/CODE/MRTYP/NSTFrontEnd/imgs/"+city+"__"+state+"__"+activity+"/";
		new File(outdir).mkdir();
		
		HeatMapCreator hmc = new  HeatMapCreator();
		
		hmc.printMap(files, outdir+"100/", 100);
		hmc.printMap(files, outdir+"200/", 200);
		hmc.printMap(files, outdir+"300/", 300);
				
		double north = hmc.north;
		double south = hmc.south;
		double west = hmc.west;
		double east = hmc.east;
		
		
		CityStats cs = csr.get(city, state, activity);
		
		if(cs == null) {
			System.out.println("********************"+city+"("+state+"), "+activity);
		}
		else {
			hmc.insert(city, state, activity, cs.nu, cs.nt, cs.population, north, south, west, east);
		}
		System.out.println("Done");
		
	}
	
	
	
	public static void main(String[] args) {
		
		csr = new CityStatsReader("D:/DATASETS/IN/NST_KDE/backup_1/cityTracksStatistics0-1000.csv");
		
		int tot = csr.size() / 3;
		/*
		File fdir = new File("D:/DATASETS/IN/NST_KDE/backup_1");
		File[] files = fdir.listFiles();
		for(int i=0; i<files.length;i++) {
			File f = files[i];
			if(f.isDirectory()) {
				String abs = f.getAbsolutePath();
				abs = abs.replace("\\", "/");
				System.out.println(abs);
				parseCity(abs);
				
				if((i+1)%10==0)
				System.out.println("****************"+i+" out of "+tot+" completed!");	
			}
		}
		*/
		
		//parseCity("D:/DATASETS/IN/NST_KDE/backup_1/DE-Bergisch Gladbach");
		//parseCity("D:/DATASETS/IN/NST_KDE/backup_1/US-Ann Arbor");
		//parseCity("D:/DATASETS/IN/NST_KDE/backup_1/US-Los Angeles");
		//parseCity("D:/DATASETS/IN/NST_KDE/backup_1/PE-Chiclayo");
		//parseCity("D:/DATASETS/IN/NST_KDE/backup_1/IT-Napoli");
		//parseCity("D:/DATASETS/IN/NST_KDE/backup_1/BJ-Abomey-Calavi");
		parseCity("D:/DATASETS/IN/NST_KDE/backup_1/RU-Podol’sk");
		parseCity("D:/DATASETS/IN/NST_KDE/backup_1/RU-Pskov");
		parseCity("D:/DATASETS/IN/NST_KDE/backup_1/RU-Saint Petersburg");
	}
	
}
